package com.zzz.email.service;

import com.alibaba.fastjson2.JSON;
import com.zzz.email.config.EmailConfig;
import com.zzz.email.dto.EmailSendDTO;
import com.zzz.email.util.VerificationCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import jakarta.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: oj-project
 * @BelongsPackage: com.zzz.email.service
 * @Author: zzz
 * @CreateTime: 2025-10-25  20:01
 * @Description: 邮件服务
 * @Version: 1.0
 */
@Component
@Slf4j
public class EmailService {
    
    @Autowired
    private JavaMailSender javaMailSender;
    
    @Autowired
    private EmailConfig emailConfig;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private EmailTemplateService emailTemplateService;

    /**
     * 发送邮箱验证码
     *
     * @param email 邮箱地址
     * @param code 验证码
     */
    public boolean sendEmailCode(String email, String code) {
        // 检查邮件发送通道是否开启
        if (!emailConfig.isSendMessage()) {
            log.warn("邮件发送通道关闭，不发送验证码邮件到邮箱：{}", email);
            return true;
        }
        
        // 准备参数
        Map<String, Object> params = new HashMap<>();
        params.put("code", code);
        params.put("expireMinutes", emailConfig.getVerificationCodeExpireMinutes());
        params.put("companyName", emailConfig.getCompanyName());
        
        try {
            // 使用模板服务渲染邮件内容
            String content = emailTemplateService.renderTemplate(
                emailConfig.getVerificationCodeTemplateType(),
                emailConfig.getVerificationCodeTemplatePath(),
                params
            );

            // 根据模板类型选择发送方式
            if ("html".equalsIgnoreCase(emailConfig.getVerificationCodeTemplateType())) {
                // 发送HTML邮件
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true);
                
                helper.setFrom(emailConfig.getFrom());
                helper.setTo(email);
                helper.setSubject(emailConfig.getVerificationCodeSubject());
                helper.setText(content, true);
                
                javaMailSender.send(message);
            } else {
                // 发送文本邮件
                SimpleMailMessage message = new SimpleMailMessage();
                message.setFrom(emailConfig.getFrom());
                message.setTo(email);
                message.setSubject(emailConfig.getVerificationCodeSubject());
                message.setText(content);
                
                javaMailSender.send(message);
            }

            log.info("验证码邮件发送成功，邮箱：{}，验证码：{}，模板类型：{}", email, code, emailConfig.getVerificationCodeTemplateType());
            return true;
        } catch (Exception e) {
            log.error("验证码邮件{} 发送失败，失败原因:{}.... ", email, e.getMessage());
            return false;
        }
    }

    /**
     * 使用模板发送验证码邮件
     *
     * @param email 邮箱地址
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendVerificationCodeWithTemplate(String email, String code) {
        // 检查邮件发送通道是否开启
        if (!emailConfig.isSendMessage()) {
            log.warn("邮件发送通道关闭，不发送验证码邮件到邮箱：{}", email);
            return true;
        }
        
        // 准备模板参数
        Map<String, Object> params = new HashMap<>();
        params.put("code", code);
        params.put("expireMinutes", emailConfig.getVerificationCodeExpireMinutes());
        params.put("companyName", emailConfig.getCompanyName());
        
        try {
            // 使用模板服务渲染邮件内容
            String content = emailTemplateService.renderTemplate(
                emailConfig.getVerificationCodeTemplateType(),
                emailConfig.getVerificationCodeTemplatePath(),
                params
            );

            // 根据模板类型选择发送方式
            if ("html".equalsIgnoreCase(emailConfig.getVerificationCodeTemplateType())) {
                // 发送HTML邮件
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true);
                
                helper.setFrom(emailConfig.getFrom());
                helper.setTo(email);
                helper.setSubject(emailConfig.getVerificationCodeSubject());
                helper.setText(content, true);
                
                javaMailSender.send(message);
            } else {
                // 发送文本邮件
                SimpleMailMessage message = new SimpleMailMessage();
                message.setFrom(emailConfig.getFrom());
                message.setTo(email);
                message.setSubject(emailConfig.getVerificationCodeSubject());
                message.setText(content);
                
                javaMailSender.send(message);
            }

            log.info("验证码邮件发送成功，邮箱：{}，验证码：{}，模板类型：{}", email, code, emailConfig.getVerificationCodeTemplateType());
            return true;
        } catch (Exception e) {
            log.error("验证码邮件{} 发送失败，失败原因:{}.... ", email, e.getMessage());
            return false;
        }
    }

    /**
     * 发送验证码邮件
     *
     * @param email 邮箱地址
     * @param params 参数映射
     */
    public boolean sendVerificationEmail(String email, Map<String, Object> params) {
        if (!emailConfig.isSendMessage()) {
            log.warn("邮件发送通道关闭，验证码已存储但不发送邮件......" + email);
            // 生成验证码（如果未提供）
            String code = (String) params.get("code");
            if (code == null || code.isEmpty()) {
                code = VerificationCodeUtil.generateNumericCode(emailConfig.getVerificationCodeLength());
                params.put("code", code);
            }
            
            // 将验证码存储到Redis，设置过期时间
            String key = "verification_code:" + email;
            redisTemplate.opsForValue().set(key, code, emailConfig.getVerificationCodeExpireMinutes(), TimeUnit.MINUTES);
            
            log.info("验证码已存储，邮箱：{}，验证码：{}，但未发送邮件", email, code);
            return true;
        }

        // 生成验证码（如果未提供）
        String code = (String) params.get("code");
        if (code == null || code.isEmpty()) {
            code = VerificationCodeUtil.generateNumericCode(emailConfig.getVerificationCodeLength());
            params.put("code", code);
        }

        // 添加其他参数
        params.put("expireMinutes", emailConfig.getVerificationCodeExpireMinutes());
        params.put("companyName", emailConfig.getCompanyName());

        try {
            // 使用模板服务渲染邮件内容
            String content = emailTemplateService.renderTemplate(
                emailConfig.getVerificationCodeTemplateType(),
                emailConfig.getVerificationCodeTemplatePath(),
                params
            );

            // 根据模板类型选择发送方式
            if ("html".equalsIgnoreCase(emailConfig.getVerificationCodeTemplateType())) {
                // 发送HTML邮件
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true);
                
                helper.setFrom(emailConfig.getFrom());
                helper.setTo(email);
                helper.setSubject(emailConfig.getVerificationCodeSubject());
                helper.setText(content, true);
                
                javaMailSender.send(message);
            } else {
                // 发送文本邮件
                SimpleMailMessage message = new SimpleMailMessage();
                message.setFrom(emailConfig.getFrom());
                message.setTo(email);
                message.setSubject(emailConfig.getVerificationCodeSubject());
                message.setText(content);
                
                javaMailSender.send(message);
            }

            // 将验证码存储到Redis，设置过期时间
            String key = "verification_code:" + email;
            redisTemplate.opsForValue().set(key, code, emailConfig.getVerificationCodeExpireMinutes(), TimeUnit.MINUTES);

            log.info("验证码邮件发送成功，邮箱：{}，验证码：{}，模板类型：{}", email, code, emailConfig.getVerificationCodeTemplateType());
            return true;
        } catch (Exception e) {
            log.error("验证码邮件{} 发送失败，失败原因:{}.... ", email, e.getMessage());
            return false;
        }
    }

    /**
     * 发送简单文本邮件
     *
     * @param emailSendDTO 邮件发送DTO
     */
    public boolean sendSimpleMail(EmailSendDTO emailSendDTO) {
        if (!emailConfig.isSendMessage()) {
            log.warn("邮件发送通道关闭，不发送简单邮件......" + emailSendDTO.getTo());
            return true;
        }

        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(emailConfig.getFrom());
            message.setTo(emailSendDTO.getTo());
            message.setSubject(emailSendDTO.getSubject());
            message.setText(emailSendDTO.getContent());

            javaMailSender.send(message);
            log.info("简单邮件发送成功，收件人：{}", emailSendDTO.getTo());
            return true;
        } catch (Exception e) {
            log.error("简单邮件{} 发送失败，失败原因:{}.... ", JSON.toJSONString(emailSendDTO), e.getMessage());
            return false;
        }
    }

    /**
     * 发送HTML邮件
     *
     * @param emailSendDTO 邮件发送DTO
     */
    public boolean sendHtmlMail(EmailSendDTO emailSendDTO) {
        if (!emailConfig.isSendMessage()) {
            log.warn("邮件发送通道关闭，不发送HTML邮件......" + emailSendDTO.getTo());
            return true;
        }

        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);

            helper.setFrom(emailConfig.getFrom());
            helper.setTo(emailSendDTO.getTo());
            helper.setSubject(emailSendDTO.getSubject());
            helper.setText(emailSendDTO.getContent(), true);

            javaMailSender.send(message);
            log.info("HTML邮件发送成功，收件人：{}", emailSendDTO.getTo());
            return true;
        } catch (Exception e) {
            log.error("HTML邮件{} 发送失败，失败原因:{}.... ", JSON.toJSONString(emailSendDTO), e.getMessage());
            return false;
        }
    }

    /**
     * 验证验证码是否正确
     *
     * @param email 邮箱
     * @param code 验证码
     * @return 是否验证成功
     */
    public boolean verifyCode(String email, String code) {
        String key = "verification_code:" + email;
        String storedCode = redisTemplate.opsForValue().get(key);

        if (storedCode == null) {
            log.warn("验证码不存在或已过期，邮箱：{}", email);
            return false;
        }

        boolean isValid = storedCode.equals(code);
        if (isValid) {
            // 验证成功后删除验证码
            redisTemplate.delete(key);
            log.info("验证码验证成功，邮箱：{}", email);
        } else {
            log.warn("验证码验证失败，邮箱：{}，输入验证码：{}，存储验证码：{}", email, code, storedCode);
        }

        return isValid;
    }

    public String generateCode(Integer codeQuantity) {
        // 定义验证码字符集：数字0-9，大小写字母a-z，A-Z
        String charSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder code = new StringBuilder();

        // 使用传入的codeQuantity作为验证码长度
        int codeLength = codeQuantity;

        for (int i = 0; i < codeLength; i++) {
            // 生成随机索引，范围0到charSet.length()-1
            int index = (int) (Math.random() * charSet.length());
            // 根据索引获取字符并添加到验证码中
            code.append(charSet.charAt(index));
        }

        return code.toString();
    }
}